#include "net/flow_status.h"

static uint32_t s_send_timeout_check = 3;
static uint32_t s_send_timeout_max_num = 100;

static uint32_t s_recv_timeout_check = 3;
static uint32_t s_recv_timeout_max_num = 1000;

static uint32_t s_expire_time = 6;

namespace weilin
{
	FlowStatus::FlowStatus() : m_expire_time(0)
	{

	}

	FlowStatus::~FlowStatus()
	{
		m_send_timeout_map.clear();
		m_recv_timeout_map.clear();
	}

	bool FlowStatus::IsBusy()
	{
		scope_mutex_locker scoper_locker(m_mutex);
		uint32_t now = time(NULL);
		if (m_expire_time > now)
		{
			return true;
		}

		uint32_t key = now/s_recv_timeout_check;
		boost::unordered_map<uint32_t, uint32_t>::const_iterator send_map_it = m_send_timeout_map.find(key);
		if (send_map_it !=  m_send_timeout_map.end() && send_map_it->second > s_send_timeout_max_num)
		{
			m_expire_time = m_expire_time + s_expire_time;
			return false;
		}
		
		boost::unordered_map<uint32_t, uint32_t>::const_iterator recv_map_it = m_recv_timeout_map.find(key);
		if (recv_map_it !=  m_recv_timeout_map.end() && recv_map_it->second > s_recv_timeout_max_num)
		{
			m_expire_time = m_expire_time + s_expire_time;
			return false;
		}
		return true;
	}

	void FlowStatus::RecordSentTimeout()
	{
		scope_mutex_locker scoper_locker(m_mutex);
		uint32_t now = time(NULL);
		uint32_t key = now/s_send_timeout_check;
		boost::unordered_map<uint32_t, uint32_t>::iterator send_map_it = m_send_timeout_map.find(key);
		if (send_map_it == m_send_timeout_map.end())
		{
			m_send_timeout_map[now] = 1;
			return;
		}
		send_map_it->second++;
	}


	void FlowStatus::RecordRecvTimeout()
	{
		scope_mutex_locker scoper_locker(m_mutex);
		uint32_t now = time(NULL);
		uint32_t key = now/s_recv_timeout_check;
		boost::unordered_map<uint32_t, uint32_t>::iterator recv_map_it = m_recv_timeout_map.find(key);
		if (recv_map_it == m_recv_timeout_map.end())
		{
			m_recv_timeout_map[now] = 1;
			return;
		}
		recv_map_it->second++;
	}

	void FlowStatus::ClearRecord()
	{   
		scope_mutex_locker scoper_locker(m_mutex);
		uint32_t now = time(NULL);
		uint32_t key = now/s_recv_timeout_check;
		
		boost::unordered_map<uint32_t, uint32_t>::const_iterator send_map_it = m_send_timeout_map.find(key);
		if (send_map_it !=  m_send_timeout_map.end())
		{
			m_send_timeout_map.erase(send_map_it, m_send_timeout_map.end());
		}
		else
		{
			m_send_timeout_map.clear();
		}	
	
		boost::unordered_map<uint32_t, uint32_t>::const_iterator recv_map_it = m_recv_timeout_map.find(key);
		if (recv_map_it !=  m_recv_timeout_map.end())
		{
			m_send_timeout_map.erase(recv_map_it, m_recv_timeout_map.end());
		}
		else
		{
			m_recv_timeout_map.clear();
		}
	}  	

}

